package tec;

import java.util.Iterator;
import java.util.ArrayList;

class Autobus 
    implements Bus, Transport {
    
    
    private final JaugeNaturel nbAssis;
    private final JaugeNaturel nbDebout;
    private int arret;
    private final ArrayList<Passager> passagers;
    
	
    public Autobus(int nbPlaceAssise, int nbPlaceDebout) {
	if(nbPlaceAssise < 0 || nbPlaceDebout < 0)
	    throw new IllegalArgumentException("nbPlaceAssise et/ou nbPlaceDebout negatif ou nul");
	passagers = new ArrayList(nbPlaceAssise + nbPlaceDebout);
	nbAssis =  new JaugeNaturel(0,nbPlaceAssise,0);
	nbDebout = new JaugeNaturel(0,nbPlaceDebout,0);
	arret = 0;

    }
    

  public boolean aPlaceAssise() {
      
      return !(nbAssis.estRouge());
  }

  public boolean aPlaceDebout() {
      return !(nbDebout.estRouge());
  }

  public void demanderPlaceAssise(Passager p) {
      if(!p.estDehors())
	  throw new IllegalStateException("Passenger Already In Bus");
      nbAssis.incrementer();
      passagers.add(p);
      p.accepterPlaceAssise();
      
  }

  public  void demanderPlaceDebout(Passager p) {
      if(!p.estDehors())
	  throw new IllegalStateException("Passenger Already In Bus");
      nbDebout.incrementer();
      passagers.add(p);
      p.accepterPlaceDebout();
      
  }

  public  void demanderSortie(Passager p) {
      
      if(p.estAssis()){
	  nbAssis.decrementer();
	  p.accepterSortie();
      }
      else{
	  if(p.estDebout()){
	      nbDebout.decrementer();
	      p.accepterSortie();
	  }
      }
      passagers.remove(p);
  }
    
    private void nouvelleSortie(Iterator<Passager> place, Passager p){
	place.remove();
	if(p.estDehors())
	    throw new IllegalStateException("Passenger Already Out");
	if(p.estAssis()){
	    nbAssis.decrementer();
	    p.accepterSortie();
	}
	else{
	    if(p.estDebout()){
		nbDebout.decrementer();
		p.accepterSortie();
	    }
	}
    }
    
    public   void demanderChangerEnDebout(Passager p) {
      if(p.estDebout())
	  throw new IllegalStateException("Passenger Already Standing");
	nbAssis.decrementer();
	nbDebout.incrementer();
	p.accepterPlaceDebout();
    }
    
  public  void demanderChangerEnAssis(Passager p) {
      if(p.estAssis())
	  throw new IllegalStateException("Passenger Already Seated");
	nbAssis.incrementer();
	nbDebout.decrementer();
	p.accepterPlaceAssise();
	
    }

    public void allerArretSuivant() throws TecInvalidException{ 
	arret++;
	
	    final Iterator<Passager> passagerIte = passagers.iterator();
		Bus bus = new Bus(){
		public  void demanderSortie(Passager p) {
		    nouvelleSortie(passagerIte, p);
		    Autobus.this.demanderSortie(p);
		    
		}
			public void demanderPlaceAssise(Passager p){
		    throw new IllegalStateException("Passenger Already in Bus");
		}
			
			public void demanderPlaceDebout(Passager p){
		    throw new IllegalStateException("Passenger Already in Bus");
		    
		}
			public boolean aPlaceAssise(){
		    return Autobus.this.aPlaceAssise();
		    
		}
			public boolean aPlaceDebout(){
		    return Autobus.this.aPlaceDebout();
		}
			public void demanderChangerEnDebout(Passager p){
		    Autobus.this.demanderChangerEnDebout(p);
		}
			public void demanderChangerEnAssis(Passager p){
		    Autobus.this.demanderChangerEnAssis(p);
		}
			public void allerArretSuivant() throws TecInvalidException{
		    Autobus.this.allerArretSuivant();
		}
		    };
		while(passagerIte.hasNext()){
		    
		    try{
			passagerIte.next().nouvelArret(bus, arret);
			
		    }
		    catch(IllegalStateException e){
			throw new TecInvalidException(e);
		    }
		}
		
    }    
    
    
    
    @Override
    public String toString() {
	
	return "[arret:" + arret + ", assis:" + nbAssis.toString() + ", debout:" + nbDebout.toString() + "]";
    }
    
}
